package de.jmda.mview.fx.node.typeshape.relation;

import javafx.beans.property.ObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Point2D;
import javafx.scene.input.MouseEvent;

import org.apache.log4j.Logger;

import de.jmda.fx.node.ArrowOrthogonal;
import de.jmda.fx.node.behaviour.BehaviourMouseDraggingStop;

/**
 * @author roger.jmda@gmail.com
 */
public class RelationSegmentHorizontalToEndpoint
    extends RelationSegmentHorizontal
{
	private final static Logger LOGGER =
      Logger.getLogger(RelationSegmentHorizontalToEndpoint.class);

	private ArrowOrthogonal arrow;
	private double arrowMinLength;

	public RelationSegmentHorizontalToEndpoint(
			ObjectProperty<Point2D> start,
			ObjectProperty<Point2D> xEndProvider,
			RelationEndpoint endpoint)
	{
		super(start, xEndProvider);

		arrow = endpoint.getArrow();
		arrowMinLength = arrow.getLength();

		arrow.layoutXProperty()
		     .addListener(
		    		 new ArrowLayoutCoordinateChangeListener<Double>("x", arrow));
		arrow.layoutYProperty()
		     .addListener(
		    		 new ArrowLayoutCoordinateChangeListener<Double>("y", arrow));
	}

	@Override
	public void activateDragging()
	{
		BehaviourMouseDraggingData behaviourMouseDraggingData =
				new BehaviourMouseDraggingData();

		new BehaviourMouseDraggingStartLine(
				this, behaviourMouseDraggingData);
		new BehaviourMouseDraggingStop(
				this, behaviourMouseDraggingData);
		new BehaviourMouseDraggingLineHorizontalToEndpoint(
				this, behaviourMouseDraggingData);
	}

	public class BehaviourMouseDraggingLineHorizontalToEndpoint
			extends BehaviourMouseDraggingLineHorizontal
	{
		public BehaviourMouseDraggingLineHorizontalToEndpoint(
				RelationSegmentHorizontalToEndpoint relationSegmentHorizontalToEndpoint,
				BehaviourMouseDraggingData behaviourMouseDraggingData)
    {
	    super(relationSegmentHorizontalToEndpoint, behaviourMouseDraggingData);
    }

		@Override
	  public void showBehaviour(MouseEvent mouseEventCurrent)
	  {
//			LOGGER.debug(
//					"entering show: " +
//					ArrowOrthogonal.coordinatesAsString(arrow) + " " +
//					ArrowOrthogonal.boundsAsString(arrow.getBoundsInParent()));
			
			super.showBehaviour(mouseEventCurrent);

//			arrow.setLayoutX(0);
//			arrow.setLayoutY(0);
			
			double yDrag =
					getLineDraggingData(
							mouseEventCurrent, line, behaviourMouseDraggingData).getDragY();
			
			double yNew = line.getStartPoint().getY() + yDrag;
			
			double lengthNew = Math.abs(arrow.getHead().getY() - yNew);

//			LOGGER.debug(
//					"before setlen: " +
//					ArrowOrthogonal.coordinatesAsString(arrow) + " " +
//					ArrowOrthogonal.boundsAsString(arrow.getBoundsInParent()));
//			// TODO xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
			arrow.setLength(lengthNew);
//			LOGGER.debug(
//					"after  setlen: " +
//					ArrowOrthogonal.coordinatesAsString(arrow) + " " +
//					ArrowOrthogonal.boundsAsString(arrow.getBoundsInParent()));
	  }
	}
	
	private class ArrowLayoutCoordinateChangeListener<T extends Number>
			implements ChangeListener<Number>
	{
		private String coordinate;
		private ArrowOrthogonal arrow;

		private ArrowLayoutCoordinateChangeListener(
				String coordinate, ArrowOrthogonal arrow)
    {
			super();

			this.coordinate = coordinate;
			this.arrow = arrow;
    }

		@Override
    public void changed(ObservableValue<? extends Number> observable,
    		Number oldValue, Number newValue)
    {
//			LOGGER.debug(
//					"new " + coordinate + " , " +
//					ArrowOrthogonal.coordinatesAsString(arrow));
    }
	}
}